package com.guonl.open.api.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class AtLeastOneNotEmptyValidator implements ConstraintValidator<AtLeastOneNotEmpty, Object> {
    private String[] fields;

    @Override
    public void initialize(AtLeastOneNotEmpty atLeastOneNotEmpty) {
        this.fields = atLeastOneNotEmpty.fields();
    }

    /**
     * 校验通过返回true
     * 校验失败返回false
     */
    @Override
    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
        if (object == null) {
            return true;
        }
        try {
            List<String> notGroupFileds = Arrays.stream(fields).filter(filed -> !(filed.startsWith("(") && filed.endsWith(")"))).collect(Collectors.toList());
            for (String fieldName : notGroupFileds) {
                Object property = getField(object, fieldName);
                if (property != null && !"".equals(property)) {
                    return true;
                }
            }

            List<Boolean> allGroupValidResult = new ArrayList<>();
            List<String> groupFileds = Arrays.stream(fields).filter(filed -> (filed.startsWith("(") && filed.endsWith(")"))).collect(Collectors.toList());
            if (groupFileds != null && groupFileds.size() > 0) {
                for (String fieldName : groupFileds) {
                    String replace = fieldName.replace("(", "").replace(")", "");
                    String[] fileds = replace.split(",");
                    List<Object> groupFiledValues = new ArrayList<>();
                    for (String filed : fileds) {
                        Object property = getField(object, filed);
                        groupFiledValues.add(property);
                    }
                    List<Object> collect = groupFiledValues.stream().filter(property -> (property == null || "".equals(property))).collect(Collectors.toList());
                    if (collect != null && collect.size() > 0) {
                        allGroupValidResult.add(Boolean.FALSE);
                    } else {
                        allGroupValidResult.add(Boolean.TRUE);
                    }
                }
            }

            List<Boolean> collect = allGroupValidResult.stream().filter(item -> item).collect(Collectors.toList());
            if (collect != null && collect.size() > 0) {
                return true;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private Object getField(Object object, String fieldName) throws IllegalAccessException {
        if (object == null) {
            return null;
        }
        Class clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.getName().equals(fieldName)) {
                field.setAccessible(true);
                return field.get(object);
            }
        }
        return null;
    }
}
